<?php

namespace App\Models;

use App\Notifications\ResetPassword;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Facades\Auth;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */

    public function statuses()
    {
        return $this->hasMany(Status::class);
    }


    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /* 用户通用头像 gravatar
     *
     * */
    public function gravatar($size = 140)
    {
        /*使用$this->attributes['email'] 或者 $this->email 没有本质上的区别，
        $this->email 在框架底层还是会调用 $this->attributes['email]
        当使用 $user->email时, 因为 User.php 和它所继承的类(父类或者 trait) 中都没有email这个属性,这时候会调用 Model类 的 __get() 这个魔术方法。
        */
        $hash = md5(strtolower($this->attributes['email']));
//        $hash = md5(strtolower($this->email));
        return "http://www.gravatar.com/avatar/$hash?s=$size";
    }

    /* 生成密码重置 token */
    public static  function boot()
    {
        parent::boot(); // TODO: Change the autogenerated stub
        static::creating(function($user){
            $user->activation_token=str_random(30);
        });
    }

    /*发送邮件通知*/

    public function sendPasswordResetNotification($token)
    {
        $this->notify(new ResetPassword($token));
    }

    public function feed()
    {
        $user_ids = Auth::user()->followings->pluck('id')->toArray();
        array_push($user_ids,Auth::user()->id);

        /*return $this->statuses()
                    ->orderBy('created_at','desc');*/
        /*通过 followings 方法取出所有关注用户的信息，再借助 pluck 方法将 id 进行分离并赋值给 user_ids；
        将当前用户的 id 加入到 user_ids 数组中；
        使用 Laravel 提供的 查询构造器 whereIn 方法取出所有用户的微博动态并进行倒序排序；
        我们使用了 Eloquent 关联的 预加载 with 方法，预加载避免了 N+1 查找的问题，大大提高了查询效率。N+1 问题 的例子可以阅读此文档 Eloquent 模型关系预加载 。
        这里需要注意的是 Auth::user()->followings 的用法。我们在 User 模型里定义了关联方法 followings()，关联关系定义好后，我们就可以通过访问 followings 属性直接获取到关注用户的 集合。
        这是 Laravel Eloquent 提供的「动态属性」属性功能，我们可以像在访问模型中定义的属性一样，来访问所有的关联方法。

        还有一点需要注意的是 $user->followings 与 $user->followings() 调用时返回的数据是不一样的， $user->followings 返回的是 Eloquent：集合 。
        而 $user->followings() 返回的是 数据库请求构建器 ，followings() 的情况下，你需要使用：

        $user->followings()->get()
        或者 ：

        $user->followings()->paginate()
        方法才能获取到最终数据。可以简单理解为 followings 返回的是数据集合，而 followings() 返回的是数据库查询语句。如果使用 get() 方法的话：

        $user->followings == $user->followings()->get()*/
        return Status::whereIn('user_id',$user_ids)
                        ->with('user')
                        ->orderBy('created_at','desc');
    }

    /* 获取用户粉丝 */
    public function followers()
    {
        return $this->belongsToMany(User::class,'followers','user_id','follower_id');
    }

    /*获取关注的人*/
    public function followings()
    {
        return $this->belongsToMany(User::class,'followers','follower_id','user_id');
    }

    /*关注用户*/
    public function follow($user_ids)
    {
        if(!is_array($user_ids)){
            $user_ids = compact('user_ids');

        }

        /*为了解决这种问题，我们可以使用 sync 方法。sync 方法会接收两个参数，第一个参数为要进行添加的 id，
        第二个参数则指明是否要移除其它不包含在关联的 id 数组中的 id，true 表示移除，false 表示不移除，
        默认值为 true。由于我们在关注一个新用户的时候，仍然要保持之前已关注用户的关注关系，因此不能对其进行移除，所以在这里我们选用 false*/
        $this->followings()->sync($user_ids,false);
    }

    /* 取消关注 */
    public function unfollow($user_ids)
    {
        if(!is_array($user_ids)){
            $user_ids = compact('user_ids');
        }

        $this->followings()->detach($user_ids);
    }

    /*接下来我们还需要一个方法用于判断当前登录的用户 A 是否关注了用户 B，
    代码实现逻辑很简单，我们只需要判断用户 B 是否包含在用户 A 的关注人列表上即可。这里我们将用到 contains 方法来做判断*/

    public function isFollowing($user_id)
    {
        /*因为contains方法是Collection类的一个方法，$this->followings返回的是一个Collection类的实例，也就是一个集合，
        但是$this->followings()返回的是一个Relations，没有contains方法，所以不能加括号*/

        /*// 1. 返回的是一个 HasMany 对象
            $this->followings()
            // 2. 返回的是一个 Collection 集合
            $this->followings
            // 3. 第2个其实相当于这样
            $this->followings()->get()
            // 如果不需要条件直接使用 2 那样，写起来更短*/
        return $this->followings->contains($user_id);
    }


}
